import * as Cesium from "cesium"
import {
  DrawerBase,
  EventsConfig,
  CesiumEvent,
} from "../Draw/baseDrawers/DrawerBase"
import type { MeasureStyle } from "./style"
import { defaultStyle } from "./style"

/**
 * @description 支持顶点编辑的测量基类
 */
export class BaseMeasure extends DrawerBase {
  constructor(
    viewer: Cesium.Viewer,
    public styleOption?: MeasureStyle,
  ) {
    super(viewer, styleOption)
    //实例化时注册顶点操作相关事件
    this.initVertexMoveFun()
  }
  protected events: EventsConfig = {}
  protected helpers: Cesium.Entity.ConstructorOptions[] = []

  //#region------------------顶点编辑----------------
  //收集完成测量的要素的坐标集合
  protected measuredFeature: {
    featureId: string
    positions: Cesium.Cartesian3[]
  }[] = []
  protected isVertexDragging: boolean = false //是否正在拖动顶点
  protected pickedPositionIndex: number = -1 //拾取到的顶点
  protected editingFeature?: {
    featureId: string
    positions: Cesium.Cartesian3[]
  }
  //事件
  vertexEditEvts: CesiumEvent[] = [
    //寻找拾取顶点的索引及要素坐标引用
    {
      type: "mousemove",
      callback: (e: Cesium.ScreenSpaceEventHandler.MotionEvent) => {
        //测量或拖动状态下不进行拾取
        if (this.isEditing || this.isVertexDragging) return

        //拾取点类型实体
        const [entity] = this.scene
          .drillPick(e.endPosition, 5, 5, 5)
          .filter((item) => item.id && item.id.point)
          .map((item) => item.id)
        if (entity) {
          //如果拾取到顶点，寻找对应要素及顶点索引
          let currentIndex = -1
          const currentEditingFeature = this.measuredFeature.find((feature) =>
            feature.positions.find((item, index) => {
              if (item.equals(entity.position.getValue())) {
                currentIndex = index
                return true
              } else {
                return false
              }
            }),
          )

          //对比当前状态和上次状态，如果有变化则更新
          if (
            currentIndex !== this.pickedPositionIndex &&
            currentEditingFeature?.featureId !== this.editingFeature?.featureId
          ) {
            this.pickedPositionIndex = currentIndex
            this.editingFeature = currentEditingFeature
          }
        } else {
          //如果没有拾取到顶点，初始化状态
          this.pickedPositionIndex = -1
          this.editingFeature = undefined
        }
      },
    },
    //鼠标按下激活拖动状态
    {
      type: "leftdown",
      callback: () => {
        if (this.pickedPositionIndex != -1) {
          this.isVertexDragging = true
          //禁用相机控制器
          this.viewer.scene.screenSpaceCameraController.enableInputs = false
        }
      },
    },
    //鼠标弹起退出拖动状态
    {
      type: "leftup",
      callback: () => {
        this.isVertexDragging = false
        //恢复相机控制器
        this.viewer.scene.screenSpaceCameraController.enableInputs = true
      },
    },
    //拖动状态下的鼠标移动
    {
      type: "mousemove",
      callback: (e: Cesium.ScreenSpaceEventHandler.MotionEvent) => {
        if (this.isVertexDragging) {
          const position = this.scene.pickPosition(e.endPosition)

          //更新坐标
          if (this.editingFeature) {
            this.editingFeature.positions[this.pickedPositionIndex] = position
          }
        }
      },
    },
  ]
  //辅助实体
  vertexEditHelpers: Cesium.Entity[] = []
  //#endregion

  //重写销毁方法
  public destroy(): void {
    this.end()
    this.beforeDestroy()
    this.viewer.dataSources.remove(this.dataSource)
    this.offVertexMoveFun()
  }

  //重写样式合并方法
  protected mergeStyles(option: Cesium.Entity.ConstructorOptions): void {
    // 定义可合并的样式类型
    const styleTypes = ["point", "polyline", "polygon", "label"] as const

    //合并样式
    styleTypes.forEach((type) => {
      if (option[type]) {
        option[type] = {
          ...defaultStyle[type], // 默认样式
          ...this.styleOption?.[type], // 用户样式
          ...option[type], // 方法传入样式
        } as any
      }
    })
  }

  //注册顶点编辑功能
  protected initVertexMoveFun() {
    this.enableEvents({
      cesiumEvents: this.vertexEditEvts,
    })

    //拾取到顶点时高亮
    const entity = this.entities.add({
      position: new Cesium.CallbackPositionProperty(
        () => this.editingFeature?.positions[this.pickedPositionIndex],
        false,
      ),
      point: {
        ...defaultStyle.heightLightPoint,
        ...this.styleOption?.heightLightPoint,
      },
    })
    this.vertexEditHelpers.push(entity)
  }

  //注销顶点编辑功能相关事件及状态
  protected offVertexMoveFun() {
    this.removeEvents({
      cesiumEvents: this.vertexEditEvts,
    })
    this.vertexEditHelpers.forEach((item) => this.entities.remove(item))
  }
}
